CREATE OR REPLACE FUNCTION func_addColumns() RETURNS void AS $$
DECLARE
    VCOUNT  INTEGER := 0;
BEGIN
  SELECT count(*) into VCOUNT FROM pg_attribute WHERE attrelid='HYDRA_REQUEST'::REGCLASS AND attname = 'TP_REQ';
  IF VCOUNT = 0 THEN
      ALTER TABLE <OWNER>.HYDRA_REQUEST ADD TP_REQ NUMERIC(1, 0);
  END IF;
  SELECT count(*) into VCOUNT FROM pg_attribute WHERE attrelid='HYDRA_REQUEST'::REGCLASS AND attname = 'COD_HYDRA_SYSTEM';
  IF VCOUNT = 0 THEN
      ALTER TABLE <OWNER>.HYDRA_REQUEST ADD COD_HYDRA_SYSTEM NUMERIC(20, 0);
  END IF;
  SELECT count(*) into VCOUNT FROM pg_attribute WHERE attrelid='HYDRA_REQUEST'::REGCLASS AND attname = 'COD_HYDRA_SPEC';
  IF VCOUNT = 0 THEN
      ALTER TABLE <OWNER>.HYDRA_REQUEST ADD COD_HYDRA_SPEC NUMERIC(20, 0);
  END IF;
  SELECT count(*) into VCOUNT FROM pg_attribute WHERE attrelid='HYDRA_REQUEST'::REGCLASS AND attname = 'REQUEST_SUMMARY';
  IF VCOUNT = 0 THEN
      ALTER TABLE <OWNER>.HYDRA_REQUEST ADD REQUEST_SUMMARY VARCHAR(255);
  END IF;
  SELECT count(*) into VCOUNT FROM pg_attribute WHERE attrelid='HYDRA_ACTION'::REGCLASS AND attname = 'COD_HYDRA_REQUEST';
  IF VCOUNT = 0 THEN
    ALTER TABLE <OWNER>.HYDRA_ACTION ADD COD_HYDRA_REQUEST NUMERIC(20, 0);
  END IF;
  SELECT count(*) into VCOUNT FROM pg_attribute WHERE attrelid='HYDRA_ACTIVATION'::REGCLASS AND attname = 'COD_HYDRA_SYSTEM';
  IF VCOUNT = 0 THEN
    ALTER TABLE <OWNER>.HYDRA_ACTIVATION ADD COD_HYDRA_SYSTEM NUMERIC(20, 0);
  END IF;
  RETURN;
END;
$$ LANGUAGE plpgsql;
SELECT func_addColumns();
DROP FUNCTION func_addColumns();

COMMENT ON COLUMN <OWNER>.HYDRA_REQUEST.TP_REQ IS 'TIPO DE REQUISICAO. 0 - ENVIO, 1 - RECEBIMENTO';
COMMENT ON COLUMN <OWNER>.HYDRA_REQUEST.COD_HYDRA_SYSTEM IS 'CODIGO DO SISTEMA ASSOCIADO A REQUISICAO';
COMMENT ON COLUMN <OWNER>.HYDRA_REQUEST.COD_HYDRA_SPEC IS 'CODIGO DA ESPECIFICACAO DISPARADA PELA REQUISICAO.';
COMMENT ON COLUMN <OWNER>.HYDRA_REQUEST.REQUEST_SUMMARY IS 'RESUMO DA REQUISICAO.';
COMMENT ON COLUMN <OWNER>.HYDRA_ACTION.COD_HYDRA_REQUEST IS 'CODIGO DA REQUISICAO QUE GEROU ESTA ACAO.';
COMMENT ON COLUMN <OWNER>.HYDRA_ACTIVATION.COD_HYDRA_SYSTEM IS 'CODIGO DO SISTEMA HYDRA ASSOCIADO A ESTA ATIVACAO.';

ALTER TABLE <OWNER>.HYDRA_REQUEST ADD CONSTRAINT FK_HYDSYS_HYDREQ FOREIGN KEY (COD_HYDRA_SYSTEM) REFERENCES <OWNER>.HYDRA_SYSTEM (COD_HYDRA_SYSTEM);
ALTER TABLE <OWNER>.HYDRA_REQUEST ADD CONSTRAINT FK_HYDSPC_HYDREQ FOREIGN KEY (COD_HYDRA_SPEC) REFERENCES <OWNER>.HYDRA_SPEC (COD_HYDRA_SPEC);
ALTER TABLE <OWNER>.HYDRA_ACTION ADD CONSTRAINT FK_HYDREQ_HYACTI FOREIGN KEY (COD_HYDRA_REQUEST) REFERENCES <OWNER>.HYDRA_REQUEST (COD_HYDRA_REQUEST);
ALTER TABLE <OWNER>.HYDRA_ACTIVATION ADD CONSTRAINT FK_HYDSYS_HYDACT FOREIGN KEY (COD_HYDRA_SYSTEM) REFERENCES <OWNER>.HYDRA_SYSTEM (COD_HYDRA_SYSTEM);

CREATE INDEX IX_HYDREQ_JT_2 ON <OWNER>.HYDRA_REQUEST (COD_HYDRA_SYSTEM ASC);
CREATE INDEX IX_HYDREQ_JT_3 ON <OWNER>.HYDRA_REQUEST (COD_HYDRA_SPEC ASC);
CREATE INDEX IX_HYACTI_JT_7 ON <OWNER>.HYDRA_ACTION (COD_HYDRA_REQUEST ASC);
CREATE INDEX IX_HYDACT_JT_1 ON <OWNER>.HYDRA_ACTIVATION (COD_HYDRA_SYSTEM ASC);

CREATE OR REPLACE FUNCTION func_migra_hydra_request() RETURNS void AS $$
DECLARE
    V_REC RECORD;
BEGIN
      FOR V_REC IN SELECT A.COD_HYDRA_REQUEST, B.COD_HYDRA_ACTION, B.TP_HYDRA_ACTION
                       FROM <OWNER>.HYDRA_REQUEST A, <OWNER>.HYDRA_ACTION B
                       WHERE A.COD_HYDRA_ACTION = B.COD_HYDRA_ACTION LOOP
        IF V_REC.TP_HYDRA_ACTION = 4 THEN
          UPDATE <OWNER>.HYDRA_REQUEST SET TP_REQ = 0;
        ELSE
          UPDATE <OWNER>.HYDRA_REQUEST SET TP_REQ = 1;
        END IF;
        UPDATE <OWNER>.HYDRA_ACTION SET COD_HYDRA_REQUEST = V_REC.COD_HYDRA_REQUEST WHERE COD_HYDRA_ACTION = V_REC.COD_HYDRA_ACTION;
      END LOOP;
      UPDATE <OWNER>.HYDRA_REQUEST SET TP_REQ = 0 WHERE COD_HYDRA_ACTION IS NULL;
      RETURN;
END;
$$ LANGUAGE plpgsql;
SELECT func_migra_hydra_request();
DROP FUNCTION func_migra_hydra_request();

CREATE OR REPLACE FUNCTION func_migra_hydra_action() RETURNS void AS $$
DECLARE
    VCOUNT  INTEGER := 1;
    LAST_VCOUNT  INTEGER := 0;
    V_REC RECORD;
BEGIN
      UPDATE <OWNER>.HYDRA_ACTION SET COD_HYDRA_ACTION_PAI = NULL WHERE COD_HYDRA_REQUEST IS NOT NULL;
      WHILE VCOUNT > 0 AND LAST_VCOUNT <> VCOUNT LOOP
        FOR V_REC IN SELECT A.COD_HYDRA_ACTION, B.COD_HYDRA_REQUEST
                     FROM <OWNER>.HYDRA_ACTION A, <OWNER>.HYDRA_ACTION B
                     WHERE
                         A.COD_HYDRA_ACTION_PAI = B.COD_HYDRA_ACTION
                     AND B.COD_HYDRA_REQUEST IS NOT NULL LOOP
          UPDATE <OWNER>.HYDRA_ACTION SET COD_HYDRA_REQUEST = V_REC.COD_HYDRA_REQUEST, COD_HYDRA_ACTION_PAI = NULL
                                      WHERE COD_HYDRA_ACTION = V_REC.COD_HYDRA_ACTION;
        END LOOP;
        LAST_VCOUNT = VCOUNT;
        SELECT COUNT(*) INTO VCOUNT FROM <OWNER>.HYDRA_ACTION WHERE COD_HYDRA_ACTION_PAI IS NOT NULL;
      END LOOP;
      DELETE FROM <OWNER>.HYDRA_ACTION WHERE COD_HYDRA_REQUEST IS NULL;
      RETURN;
END;
$$ LANGUAGE plpgsql;
SELECT func_migra_hydra_action();
DROP FUNCTION func_migra_hydra_action();

CREATE OR REPLACE FUNCTION func_migra_system_spec_para_request() RETURNS void AS $$
DECLARE
    V_REC RECORD;
BEGIN
      FOR V_REC IN SELECT COD_HYDRA_REQUEST, COD_HYDRA_SYSTEM, COD_HYDRA_SPEC
                   FROM <OWNER>.HYDRA_ACTION
                   WHERE
                      COD_HYDRA_SYSTEM IS NOT NULL
                   OR COD_HYDRA_SPEC IS NOT NULL LOOP
        IF V_REC.COD_HYDRA_SYSTEM IS NOT NULL THEN
          UPDATE <OWNER>.HYDRA_REQUEST SET COD_HYDRA_SYSTEM = V_REC.COD_HYDRA_SYSTEM;
        END IF;
        IF V_REC.COD_HYDRA_SPEC IS NOT NULL THEN
          UPDATE <OWNER>.HYDRA_REQUEST SET COD_HYDRA_SPEC = V_REC.COD_HYDRA_SPEC;
        END IF;
      END LOOP;
      RETURN;
END;
$$ LANGUAGE plpgsql;
SELECT func_migra_system_spec_para_request();
DROP FUNCTION func_migra_system_spec_para_request();

CREATE OR REPLACE FUNCTION func_dropColumn() RETURNS void AS $$
DECLARE
    VCOUNT  INTEGER := 0;
BEGIN
  SELECT count(*) INTO VCOUNT FROM pg_attribute WHERE attrelid='HYDRA_ACTION'::REGCLASS AND attname = 'COD_HYDRA_ACTION_PAI';
  IF VCOUNT = 1 THEN
      ALTER TABLE <OWNER>.HYDRA_ACTION DROP COLUMN COD_HYDRA_ACTION_PAI;
  END IF;
  SELECT count(*) INTO VCOUNT FROM pg_attribute WHERE attrelid='HYDRA_ACTION'::REGCLASS AND attname = 'COD_HYDRA_SYSTEM';
  IF VCOUNT = 1 THEN
      ALTER TABLE <OWNER>.HYDRA_ACTION DROP COLUMN COD_HYDRA_SYSTEM;
  END IF;
  SELECT count(*) INTO VCOUNT FROM pg_attribute WHERE attrelid='HYDRA_ACTION'::REGCLASS AND attname = 'COD_HYDRA_SPEC';
  IF VCOUNT = 1 THEN
      ALTER TABLE <OWNER>.HYDRA_ACTION DROP COLUMN COD_HYDRA_SPEC;
  END IF;
  RETURN;
END;
$$ LANGUAGE plpgsql;
SELECT func_dropColumn();
DROP FUNCTION func_dropColumn();

-- migração de dados de postscript, depende do produto

ALTER TABLE <OWNER>.HYDRA_REQUEST ALTER COLUMN TP_REQ SET NOT NULL;
ALTER TABLE <OWNER>.HYDRA_ACTION ALTER COLUMN COD_HYDRA_REQUEST SET NOT NULL;
ALTER TABLE <OWNER>.HYDRA_ACTIVATION ALTER COLUMN COD_HYDRA_SYSTEM SET NOT NULL;

CREATE OR REPLACE FUNCTION func_dropCheckConstraint() RETURNS void AS $$
DECLARE
    VCOUNT  INTEGER := 0;
BEGIN
  SELECT COUNT(*) INTO VCOUNT FROM pg_constraint WHERE conrelid='HYDRA_REQUEST'::REGCLASS AND conname= 'CK_HYDREQ_JT_0';
  IF VCOUNT = 1 THEN
      ALTER TABLE <OWNER>.HYDRA_REQUEST DROP CONSTRAINT CK_HYDREQ_JT_0;
  END IF;
  RETURN;
END;

$$ LANGUAGE plpgsql;
SELECT func_dropCheckConstraint();
DROP FUNCTION func_dropCheckConstraint();

ALTER TABLE <OWNER>.HYDRA_REQUEST ADD CONSTRAINT CK_HYDREQ_JT_0 CHECK (TP_REQ IN (0, 1));

UPDATE <OWNER>.SCRIPT SET BODY=E'/**
 * Mnemônico: HYDRA_DECODING
 * Finalidade: INIT
 * Database ID: 12
 * 
 * Funções para decodificar um arquivo xml.
 * Variáveis disponibilizadas:
 * - context: o IntegrationContext que contém a conversa atual.
 * - document: o Document gerado a apartir do parse do XML;
 * - servicesPage: o ServicesPage disponível para a inclusão de serviços.
 * @author piercio
 */
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import jmine.tec.services.io.ServiceBean;
import jmine.tec.services.api.ActionsEnum;
import bancosys.tec.persist.base.enumx.EnumUtils;
import java.text.SimpleDateFormat;
import java.text.ParseException;

/**
 * Adiciona um serviço
 * 
 * @param name o nome do serviço.
 * @param action a ação do serviço.
 * @param parameters uma lista de parametros do serviço no formato ''nome=valor''
 */
ServiceBean addService(String name, String action, Object[] parameters) {
    ServiceBean bean = createService(name, action, parameters);
    _result.addService(bean);
    return bean;
}

/**
 * Adiciona dados para codificação e envio de uma mensagem
 * @param action action
 * @param source source
 * @deprecated não utilizar, utilize addMessage(Object)
 */
void addMessage(String action, Object source) {
    addMessage(source);
}

/**
 * Adiciona dados para codificação e envio de uma mensagem
 * @param source source
 */
void addMessage(Object source) {
    _result.addMessage(source);
}

/**
 * Adiciona um serviço e os parametros adicionais do mapa "param"
 * que é carregado automaticamente no contexto de execução.
 * 
 * @param name o nome do serviço.
 * @param action a ação do serviço.
 * @param parameters uma lista de parametros do serviço no formato ''nome=valor''
 */
ServiceBean addService(String name, String action) {
    ServiceBean bean = createService(name, action);
    _result.addService(bean);
    return bean;
}

/**
 * Adiciona um serviço com a conversa e a mensagem de integração como parametros adicionais.
 * 
 * @param name o nome do serviço.
 * @param action a ação do serviço.
 * @param parameters uma lista de parametros do serviço no formato ''nome=valor''
 */
ServiceBean addServiceWithConversationMessage(String name, String action, String[] parameters) {
    ServiceBean bean = createService(name, action, parameters);
    bean.getParameters().put("HydraConversation", _message.getConversation());
    bean.getParameters().put("HydraMessage", _message);
    _result.addService(bean);
    return bean;
}

/**
 * Adiciona um serviço com a conversa e a mensagem de integração e os 
 * parametros adicionais do mapa "param" que é carregado automaticamente
 * no contexto de execução.
 * 
 * @param name o nome do serviço.
 * @param action a ação do serviço.
 */
ServiceBean addServiceWithConversationMessage(String name, String action) {
    ServiceBean bean = createService(name, action);
    bean.getParameters().put("HydraConversation", _message.getConversation());
    bean.getParameters().put("HydraMessage", _message);
    _result.addService(bean);
    return bean;
}

/**
 * Adiciona um serviço com a mensagem de integração como um dos parametros.
 * 
 * @param name o nome do serviço.
 * @param action a ação do serviço.
 * @param parameters uma lista de parametros do serviço no formato ''nome=valor''
 */
ServiceBean addServiceWithMessage(String name, String action, String[] parameters) {
    ServiceBean bean = createService(name, action, parameters);
    bean.getParameters().put("HydraMessage", _message);
    _result.addService(bean);
    return bean;
}

/**
 * Adiciona um serviço com a mensagem de integração e os parametros
 * adicionais do mapa "param" que é carregado automaticamente
 * no contexto de execução.
 *
 * @param name o nome do serviço.
 * @param action a ação do serviço.
 */
ServiceBean addServiceWithMessage(String name, String action) {
    ServiceBean bean = createService(name, action);
    bean.getParameters().put("HydraMessage", _message);
    _result.addService(bean);
    return bean;
}

/**
 * Cria um novo serviço
 * @param name o nome do serviço.
 * @param action a ação do serviço.
 * @param parameters uma lista de parametros do serviço no formato ''nome=valor''
 * @return o serviço.
 */
ServiceBean createService(String name, String action, Object[] parameters) {
    ServiceBean bean = createService(name, action);

    if (parameters != null) {
        for (int i = 0; i < parameters.length; i++) {
            String[] vals = parameters[i].toString().split("=");
            if (vals.length == 1) {
                bean.putParameter(vals[0], "");
            } else {
                bean.putParameter(vals[0], vals[1]);
            }
        }
    }
    
    return bean;
}

/**
 * Cria um novo serviço.
 *
 * @param name o nome do serviço.
 * @param action a ação do serviço.
 * @return o serviço.
 */
ServiceBean createService(String name, String action) {
    ServiceBean bean = new ServiceBean();
    bean.setName(name);
    bean.setAction(EnumUtils.getEnumByValue(ActionsEnum.class, action));
    return bean;
}

/**
 * Gera o log de execucao do hydra
 *
 * @param msg msg
 */
void log(String msg) {
    _result.addLog(msg);
}

/**
 * Método deve ser chamado quando ocorrer falha no script e a execução
 * deve ser marcada como pendente. Esta falha controlada deve ocorrer apenas
 * se for um erro de negócio. Erros de codificação não se encaixam nessa categoria.
 * Em seguida o script deve retornar e não continuar sua execução.
 */
void fail(String msg) {
    _result.fail(msg);
}

/**
 * Mesmo que o anterior, mas loga a mensagem do throwable. Esse tipo de
 * método não deveria ser usado, pois implica em um monitoramento de exceptions
 * pouco cuidadoso, em geral. Dê preferência por um log mais preciso.
 */
void fail(String msg, Throwable t) {
    _result.fail(msg, t);
}

void discardServicePage() {
    _result.discardServicePage();
}

void addServicePage() {
    _result.addNewServicesPage();
}

/**
 * Obtém o corpo da mensagem na forma de um inputStream
 */
InputStream getInput() {
    return _message.getBody();
}

/**
 * Obtém o corpo da mensagem na forma de uma String
 */
String getMessageBody() {
    return getMessageBody("UTF-8");
}

/**
 * Obtém o corpo da mensagem na forma de uma String
 * @param charsetName charsetName
 */
String getMessageBody(String charsetName) {
    return _message.getBodyAsString(charsetName);
}

/**
 * Obtém o mapa de propriedades da mensagem.
 */
Map getProperties() {
    return _message.getProperties();
}
' WHERE COD_SCRIPT = 12;

